<template>
	<div
		:class="[
			'app-editor-container',
			'app-mob-dropdown-list',
			`app-mob-dropdown-list-${name}`,
		]"
	>
		<van-field
			readonly
			type="text"
			v-model="textValue"
			:disabled="disabled"
			@click="setPopupState(true)"
		>
			<template #right-icon>
				<van-icon v-if="textValue" name="clear" @click="handleClear" />
				<van-icon name="arrow-down" />
			</template>
		</van-field>
		<van-popup
			round
			teleport="body"
			position="bottom"
			v-model:show="popupState"
			class="dropdown-list__popup"
		>
			<div class="popup__container">
				<div class="popup__header">
					<div @click="cancel" class="cancel">
						{{ $t('common.generic.onCancel', '取消') }}
					</div>
					<div @click="confirm" class="confirm">
						{{ $t('common.generic.okText', '确定') }}
					</div>
				</div>
                <div class="popup__content">
                    <template v-if="hasChildren || Object.is(editorStyle, 'cascader')">
                        <AppMobTree
                            v-bind="$attrs"
                            :fieldNames="fieldNames"
                            :multiple="multiple"
                            :items="options"
                            :selectedKeys="selectedKeys"
                            @selectionChange="handleSelectChange"
                        />
                    </template>
                    <template v-else>
                        <van-radio-group
                            v-if="!multiple"
                            v-bind="$attrs"
                            class="dropdown-list__group"
                            :disabled="disabled"
                            v-model="selectedKeys[0]"
                        >
                            <van-cell-group>
                                <van-cell
                                    v-for="(option, index) in options"
                                    clickable
                                    :key="index"
                                    :title="option.text"
                                    @click="selectedKeys = [option.value]"
                                >
                                    <template #right-icon>
                                        <van-radio
                                            class="app-mob-radio-list__item"
                                            :name="option.value"
                                            :disabled="option.disabled"
                                        ></van-radio>
                                    </template>
                                </van-cell>
                            </van-cell-group>
                        </van-radio-group>
                        <van-checkbox-group
                            v-else
                            v-bind="$attrs"
                            class="dropdown-list__group"
                            v-model="selectedKeys"
                        >
                            <van-cell-group>
                                <van-cell
                                    v-for="(item, index) in options"
                                    clickable
                                    :key="index"
                                    :title="item.text"
                                    @click="toggle(index)"
                                >
                                    <template #right-icon>
                                        <van-checkbox
                                            :key="index"
                                            :name="item.value"
                                            shape="square"
                                            :ref="(el) => (checkboxRefs[index] = el)"
                                            @click.stop
                                        />
                                    </template>
                                </van-cell>
                            </van-cell-group>
                        </van-checkbox-group>
                    </template>
                </div>
			</div>
		</van-popup>
	</div>
</template>
<script lang="ts" setup>
import { Ref } from 'vue';
import { deepCopy, ICodeListItem, IEvent, IParam, typeOf } from '@/core';
import { dropdownListProps } from './dropdown-list';
import { handleEditorNavParams, useEditorTypeParams } from '@/hooks/use-editor';
interface EditorEmit {
	(name: 'editor-event', value: IEvent<string>): void;
}
const props = defineProps(dropdownListProps);
const emit = defineEmits<EditorEmit>();
const { navContext, navViewParam } = handleEditorNavParams(props);
// 类型校验
const { 
    validateConfig, 
    valueType, 
    valueSeparator, 
    textSeparator 
} = useEditorTypeParams();
validateConfig();
/**
 * 树数据
 */
const options: Ref<any[]> = ref([]);
/**
 * 多选checkbox的ref
 */
const checkboxRefs: Ref<any[]> = ref([]);
/**
 * 模态状态
 */
const popupState = ref(false);
/**
 * 是否存在子数据
 */
const hasChildren: Ref<boolean> = ref(false);
/**
 * 选中值key集合
 */
const selectedKeys: Ref<string[]> = ref([]);
/**
 * 代码表数据集合
 */
const codeListData: Ref<ICodeListItem[]> = ref([]);
/**
 * 树节点配置
 */
const fieldNames: IParam = {
	text: 'text',
	value: 'value',
	children: 'children',
	leaf: 'isLeaf',
};
/**
 * @description 初始化选中数据
 */
const initSelectData = () => {
	if (props.multiple) {
		if (Object.is(valueType, 'SIMPLES')) {
			selectedKeys.value = (props.value as string[]) || [];
		} else {
			selectedKeys.value =
				(props.value as string)?.split(
					valueSeparator ? valueSeparator : props.valueSeparator
				) || [];
		}
	} else {
		selectedKeys.value = (props.value as string) ? [props.value as string] : [];
	}
};

watch(
	() => props.value,
	(newVal: any, oldVal: any) => {
		initSelectData();
	},
	{
		immediate: true,
	}
);
/**
 * 显示文本
 */
const textValue = computed(() => {
	let text: string = '';
	try {
		let values: string[] = selectedKeys.value;
		const textArray: string[] = [];
		if (values && values.length > 0) {
			values.forEach((value: string) => {
				const item = codeListData.value.find((codeList: ICodeListItem) =>
					Object.is(value, codeList.value)
				);
				if (item) {
					textArray.push(item.text);
				}
			});
		}
		text = textArray.join(textSeparator ? textSeparator : props.valueSeparator);
	} catch (error) {
		console.error(error);
	}
	return text;
});
/**
 * @description 设置模态状态
 * @param state  状态
 */
const setPopupState = (state: boolean) => {
	if (props.disabled) {
		return;
	}
	popupState.value = state;
};

onBeforeMount(() => {
	loadData();
});
/**
 * @description 取消
 */
const cancel = () => {
	initSelectData();
	setPopupState(false);
};
/**
 * @description 确定
 */
const confirm = () => {
	let value: any;
	if (props.multiple) {
		if (Object.is(valueType, 'SIMPLES')) {
			value =
				selectedKeys.value?.length > 0 ? deepCopy(selectedKeys.value) : null;
		} else {
			value = selectedKeys.value.join(
				valueSeparator ? valueSeparator : props.valueSeparator
			);
		}
	} else {
		value = selectedKeys.value?.length > 0 ? selectedKeys.value[0] : null;
	}
	doEditorEmit(value);
	setPopupState(false);
};
/**
 * @description 复选框切换
 */
const toggle = (index: number) => {
	checkboxRefs.value[index].toggle();
};
/**
 * @description 处理值改变
 * @param selected  选中数据集合
 */
const handleSelectChange = (selected: IParam[]) => {
	const value: string[] = [];
	selected.forEach((select: IParam) => {
		value.push(select.value);
	});
	selectedKeys.value = value;
};
/**
 * @description 加载数据
 */
const loadData = async () => {
	if (props.codeListTag && props.codeListType) {
		try {
			const codeListResult = await App.getAppCodeListHelper().getCodeListItems(
				props.codeListTag,
				navContext,
				navViewParam
			);
			if (codeListResult.ok) {
				codeListData.value = deepCopy(codeListResult.data) as ICodeListItem[];
				const result = formatCodeList(codeListResult.data);
				handleLevelCodeList(result);
			}
		} catch (error) {
			App.getNotificationHelper().error(
				App.ts('common.generic.codenotexist', '代码表不存在')
			);
		}
	}
};
/**
 * @description 格式化代码表
 * @param selected  代码表数据
 */
const formatCodeList = (items: Array<IParam>): IParam[] => {
	let matching = false;
	let result: Array<IParam> = [];
	try {
		items.forEach((item: IParam) => {
			const type = typeOf(item.value);
			if (type != props.valueType) {
				matching = true;
				if (type === 'number') {
					item.value = item.value.toString();
				} else {
					if (type == 'null') {
						props.valueType == 'number' ? (item.value = 0) : (item.value = '');
					} else if (item.value.indexOf('.') == -1) {
						item.value = parseInt(item.value);
					} else {
						item.value = parseFloat(item.value);
					}
				}
			}
			result.push(item);
		});
		if (matching) {
			console.warn(
				App.ts(
					'common.generic.codelistcast',
					'代码表值类型和属性类型不匹配，自动强制转换'
				)
			);
		}
		return result;
	} catch (error) {
		console.warn(
			App.ts(
				'common.generic.codelistwarn',
				'代码表值类型和属性类型不匹配，自动强制转换异常，请修正代码表值类型和属性类型匹配'
			)
		);
		return [];
	}
};
/**
 * @description 处理层级代码表
 * @param result  代码表数据
 */
const handleLevelCodeList = (result: IParam[]) => {
	const setChildCodeItems = (
		pValue: string,
		result: Array<IParam>,
		codeItem: IParam
    ) => {
		result.forEach((item: IParam) => {
			if (item.pvalue == pValue) {
				let valueField: string = item.value;
				setChildCodeItems(valueField, result, item);
				if (!codeItem.children) {
					codeItem.children = [];
				}
				codeItem.children.push(deepCopy(item));
			}
		});
		if (!codeItem.children || codeItem.children.length == 0) {
			codeItem.isLeaf = true;
		}
	};
	if (result && result.length > 0) {
		hasChildren.value = result.some((item: any) => {
			return item.pvalue;
		})
			? true
			: false;
		if (hasChildren.value) {
			let list: Array<IParam> = [];
			result.forEach((item: IParam) => {
				const index = result.findIndex(
					(_item: IParam) => item.pvalue == _item.value
				);
				if (index == -1) {
					list.push(deepCopy(item));
				}
			});
			list.forEach((item: IParam) => {
				setChildCodeItems(item.value, result, item);
			});
			options.value = list;
		} else {
			result.forEach((item: IParam) => {
				const _item: IParam = deepCopy(item);
				if (props.editorStyle == 'cascader') {
					Object.assign(_item, { isLeaf: true });
				}
				options.value.push(_item);
			});
		}
	}
};
/**
 * @description 统一抛出事件
 * @param value  数据
 */
const doEditorEmit = (value: any) => {
	emit('editor-event', {
		name: `${props.name}`,
		action: 'valueChange',
		data: value,
	});
};
/**
 * @description 点击清除按钮
 * @param event  事件源
 */
const handleClear = (event: MouseEvent) => {
	event.preventDefault();
	event.stopPropagation();
	doEditorEmit(null);
};
</script>
